package com.thememaker.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.thememake.Constants;
import com.thememake.entity.ThemeFileInfo;
import com.thememake.ui.Toast;
import com.thememake.ui.dialog.ProgressDialog;
import com.thememake.util.FileUtils;
import com.thememake.util.xml.fontcolor.ReadXmlUtils;
import com.thememaker.lockstyle.IntentCommandUtils;
import com.thememaker.lockstyle.LockstyleIntentDialog;
import com.thememaker.lockstyle.LockstylePaserUtils;
import com.thememaker.lockstyle.bean.Lockscreen;
import com.thememaker.lockstyle.bean.Var;
import com.thememaker.lockstyle.bean.command.*;
import com.thememaker.lockstyle.bean.ui.*;
import javafx.application.Platform;
import javafx.stage.Stage;
import net.coobird.thumbnailator.Thumbnails;
import org.w3c.dom.Document;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * @author yiyi.zheng 2018/8/30
 */
public class ThemeChangeUtils {
    private static ThemeChangeUtils themeChangeUtils;
    private ThemeFileInfo themeFileInfo;
    private File oppoPath;

    public static ThemeChangeUtils getInstance() {
        if (themeChangeUtils == null) {
            themeChangeUtils = new ThemeChangeUtils();
        }
        return themeChangeUtils;
    }

    private static boolean toastNoBG;

    public static boolean isToastNoBG() {
        return toastNoBG;
    }

    public void changeVivo2Oppo(ThemeFileInfo themeFileInfo, File oppoPath, Consumer<String> consumer) {
        this.themeFileInfo = themeFileInfo;
        this.oppoPath = oppoPath;
        toastNoBG = true;
        try {
//            File oppoPath = new File(themeFileInfo.getThemeDir() + File.separator + Constants.OPPO + File.separator + ThemeFileInfo.LOCKSTYLE_NAME + File.separator + ThemeFileInfo.LOCKSCREEN_NAME);
            File vivoPath = new File(themeFileInfo.getThemeDir() + File.separator + Constants.VIVO + File.separator + ThemeFileInfo.LOCKSTYLE_NAME + File.separator + ThemeFileInfo.LOCKSCREEN_NAME);
            FileUtils.deleteDir(oppoPath);
            FileUtils.iteratorDirToStream(vivoPath, true).forEach(file -> {
                if ("manifest.xml".equals(file.getFileName().toString())) {
                    FileUtils.copyFile(file.toString(), oppoPath + File.separator + file.getFileName(), true);
                } else if ("bg.jpg".equals(file.getFileName().toString()) ||
                        "2400.jpg".equals(file.getFileName().toString()) ||
                        "bg2400.jpg".equals(file.getFileName().toString()) ||
                        "default_lock_wallpaper.jpg".equals(file.getFileName().toString()) ||
                        "default_lock_wallpaper2400.jpg".equals(file.getFileName().toString()) ||
                        "default_lock_wallpaper_2400.jpg".equals(file.getFileName().toString())) {
                    toastNoBG = false;
                    javafx.scene.image.Image image = new javafx.scene.image.Image(file.toUri().toString());
                    if (image.getWidth() == 1080 && image.getHeight() >= 2400) {
                        copyBG(file.toFile(), oppoPath, 1080, 1920, "default_lock_wallpaper");
                        copyBG(file.toFile(), oppoPath, 1080, 2160, "default_lock_wallpaper_2160");
                        copyBG(file.toFile(), oppoPath, 1080, 2280, "default_lock_wallpaper_2280");
                        copyBG(file.toFile(), oppoPath, 1080, 2340, "default_lock_wallpaper_2340");
                    } else {
                        ErrorLogUtils.getInstance().createLog(themeFileInfo, "VIVO转OPPO壁纸不正确");
                        consumer.accept("1");
                    }
                } else {
                    String path = file.toString().replace(vivoPath.toString(), "");
                    FileUtils.copyFile(file.toString(), oppoPath + path, true);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void copyManifestFile() {
        editThemeXml(oppoPath + File.separator + "manifest.xml", Constants.OPPO);
        FileUtils.copyFile(oppoPath + File.separator + "manifest.xml", oppoPath + File.separator + "2x1" + File.separator + "manifest.xml", true);
        FileUtils.copyFile(oppoPath + File.separator + "manifest.xml", oppoPath + File.separator + "19x9" + File.separator + "manifest.xml", true);
        FileUtils.copyFile(oppoPath + File.separator + "manifest.xml", oppoPath + File.separator + "13x6" + File.separator + "manifest.xml", true);
        editOPPOWallpaper(oppoPath.toString(), "default_lock_wallpaper.jpg");
        editOPPOWallpaper(oppoPath + File.separator + "2x1", "default_lock_wallpaper_2160.jpg");
        editOPPOWallpaper(oppoPath + File.separator + "19x9", "default_lock_wallpaper_2280.jpg");
        editOPPOWallpaper(oppoPath + File.separator + "13x6", "default_lock_wallpaper_2340.jpg");
        OPPOFaceRecognitionUtils.getInstance().judgeFaceRecognition(themeFileInfo, oppoPath.toString());
    }

    public void editThemeXml(String xmlPath, String themeType) {
        Document document = ReadXmlUtils.loadXml(xmlPath);
        document.getDocumentElement().removeAttribute("showNotification");
        Lockscreen lockscreen = LockstylePaserUtils.paserLockScreenXml(document);
        LinkedHashMap<String, BaseView> map = lockscreen.getLockScreenViewMap();
        LinkedHashMap<String, BaseView> newMap = new LinkedHashMap<>();
        map.keySet().forEach(key -> {
            if (Constants.OPPO.equals(themeType)) {
                Wallpaper wallpaper = new Wallpaper();
                wallpaper.setX("#screen_width/2");
                wallpaper.setY("#screen_height/2");
                wallpaper.setAlign("center");
                wallpaper.setAlignV("center");
                wallpaper.setId("wallpaper");
                wallpaper.setName("bg");
                wallpaper.setSrc("default_lock_wallpaper.jpg");
                judgeAddMap(wallpaper, "wallpaper", newMap, false);
                analysisOppoBaseView(map.get(key), key, newMap, false);
            } else if (Constants.OS360.equals(themeType) || "os360".equals(themeType)) {
                analysis360BaseView(map.get(key), key, newMap, false);
            }
        });
        lockscreen.setLockScreenViewMap(newMap);
        LockstylePaserUtils.saveLockScreenXml(null, document, lockscreen, new File(xmlPath));
    }

    private void editOPPOWallpaper(String xmlPath, String wallpaperName) {
        String xmlM = xmlPath + File.separator + "manifest.xml";
        Document document = ReadXmlUtils.loadXml(xmlM);
        Lockscreen lockscreen = LockstylePaserUtils.paserLockScreenXml(document);
        LinkedHashMap<String, BaseView> map = lockscreen.getLockScreenViewMap();
        map.keySet().forEach(key -> {
            BaseView baseView = map.get(key);
            if (baseView instanceof Wallpaper) {
                Wallpaper wallpaper = (Wallpaper) map.get(key);
                wallpaper.setSrc(wallpaperName);
            }
        });
        lockscreen.setLockScreenViewMap(map);
        LockstylePaserUtils.saveLockScreenXml(null, document, lockscreen, new File(xmlM));
        editIntentCommand(xmlPath);
    }

    private void analysisOppoBaseView(BaseView baseView, String key, LinkedHashMap<String, BaseView> newMap, boolean isGroup) {
        if (baseView instanceof Image) {
            Image image = (Image) baseView;
            if ("bg".equals(isNullJudge(image.getName()))) {
            } else if ("ifelse(#time_format,#hour24/10,#hour12/10)".equals(isNullJudge(image.getSrcid())) ||
                    "ifelse(eq(#hour_format,24),#hour24/10,#hour12/10))".equals(isNullJudge(image.getSrcid()))) {//时上掌酷下微乐十位
                image.setSrcid("ifelse(#time_format,#hour24/10,ifelse(#ampm,ifelse(eq(#hour12,0),1,#hour12/10),#hour12/10))");
                judgeAddMap(image, key, newMap, isGroup);
            } else if ("ifelse(#time_format,#hour24%10,#hour12%10)".equals(isNullJudge(image.getSrcid())) ||
                    "ifelse(eq(#hour_format,24),#hour24%10,#hour12%10)".equals(isNullJudge(image.getSrcid()))) {//时上掌酷下微乐个位
                image.setSrcid("ifelse(#time_format,#hour24%10,ifelse(#ampm,ifelse(eq(#hour12,0),2,#hour12%10),#hour12%10))");
                judgeAddMap(image, key, newMap, isGroup);
            } else {
                judgeAddMap(image, key, newMap, isGroup);
            }
        } else if (baseView instanceof Group) {
            Group group = (Group) baseView;
            LinkedHashMap<String, BaseView> groupMap = group.getGroupViewMap();
            groupMap.keySet().forEach(groupKey -> {
                analysisOppoBaseView(groupMap.get(groupKey), groupKey, newMap, true);
            });
            newMap.put(key, group);
        } else if (baseView instanceof Slider) {
            Slider slider = (Slider) baseView;
            ReachedState reachedState = (slider.getStartPoint().getReachedState() == null) ? new ReachedState() : slider.getStartPoint().getReachedState();
            ReachedDownState reachedDownState = (slider.getStartPoint().getReachedDownState() == null) ? new ReachedDownState() : slider.getStartPoint().getReachedDownState();
            NormalState normalState = (slider.getStartPoint().getNormalState() == null) ? new NormalState() : slider.getStartPoint().getNormalState();
            PressedState pressedState = (slider.getStartPoint().getPressedState() == null) ? new PressedState() : slider.getStartPoint().getPressedState();
            ReachedUpState reachedUpState = new ReachedUpState();
            boolean addReachedUpState = false;
            if (reachedState.getDateTime() != null) {
                addReachedUpState = true;
                reachedUpState.setDateTime(reachedState.getDateTime());
            }
            if (reachedState.getGroup() != null) {
                addReachedUpState = true;
                reachedUpState.setGroup(reachedState.getGroup());
            }
            if (reachedState.getImage() != null) {
                addReachedUpState = true;
                reachedUpState.setImage(reachedState.getImage());
            }
            if (reachedState.getText() != null) {
                addReachedUpState = true;
                reachedUpState.setText(reachedState.getText());
            }
            if (reachedState.getTime() != null) {
                addReachedUpState = true;
                reachedUpState.setTime(reachedState.getTime());
            }
            if (reachedState.getTrigger() != null) {
                if (reachedState.getTrigger().getCommandMap() != null && !reachedState.getTrigger().getCommandMap().isEmpty()) {
                    reachedState.getTrigger().getCommandMap().keySet().forEach(commandKey -> {
                        BaseCommand baseCommand = reachedState.getTrigger().getCommandMap().get(commandKey);
                        if (baseCommand instanceof VariableCommand) {
                            editVarConst((VariableCommand) baseCommand);
                        }
                    });
                    addReachedUpState = true;
                    reachedUpState.setTrigger(reachedState.getTrigger());
                }
            }
            if (reachedDownState.getTrigger() != null) {
                if (reachedDownState.getTrigger().getCommandMap() != null && !reachedDownState.getTrigger().getCommandMap().isEmpty()) {
                    reachedDownState.getTrigger().getCommandMap().keySet().forEach(commandKey -> {
                        BaseCommand baseCommand = reachedDownState.getTrigger().getCommandMap().get(commandKey);
                        if (baseCommand instanceof VariableCommand) {
                            editVarConst((VariableCommand) baseCommand);
                        }
                    });
                }
            }
            if (normalState.getTrigger() != null) {
                if (normalState.getTrigger().getCommandMap() != null && !normalState.getTrigger().getCommandMap().isEmpty()) {
                    normalState.getTrigger().getCommandMap().keySet().forEach(commandKey -> {
                        BaseCommand baseCommand = normalState.getTrigger().getCommandMap().get(commandKey);
                        if (baseCommand instanceof VariableCommand) {
                            editVarConst((VariableCommand) baseCommand);
                        }
                    });
                }
            }
            if (pressedState.getTrigger() != null) {
                if (pressedState.getTrigger().getCommandMap() != null && !pressedState.getTrigger().getCommandMap().isEmpty()) {
                    pressedState.getTrigger().getCommandMap().keySet().forEach(commandKey -> {
                        BaseCommand baseCommand = pressedState.getTrigger().getCommandMap().get(commandKey);
                        if (baseCommand instanceof VariableCommand) {
                            editVarConst((VariableCommand) baseCommand);
                        }
                    });
                }
            }
            if (addReachedUpState) {
                slider.getStartPoint().setReachedUpState(reachedUpState);
            }
            slider.getStartPoint().setReachedState(null);
            judgeAddMap(slider, key, newMap, isGroup);
        } else if (baseView instanceof Wallpaper) {
//            oppoAddWallpaper = true;
        } else {
            judgeVariableCommand(baseView, key, newMap, isGroup);
        }
    }

    private void analysis360BaseView(BaseView baseView, String key, LinkedHashMap<String, BaseView> newMap, boolean isGroup) {
        if (baseView instanceof Group) {
            Group group = (Group) baseView;
            LinkedHashMap<String, BaseView> groupMap = group.getGroupViewMap();
            groupMap.keySet().forEach(groupKey -> {
                analysis360BaseView(groupMap.get(groupKey), groupKey, newMap, true);
            });
            newMap.put(key, group);
        } else if (baseView instanceof Slider) {
            Slider slider = (Slider) baseView;
            ReachedState reachedState = (slider.getStartPoint().getReachedState() == null) ? new ReachedState() : slider.getStartPoint().getReachedState();
            ReachedDownState reachedDownState = (slider.getStartPoint().getReachedDownState() == null) ? new ReachedDownState() : slider.getStartPoint().getReachedDownState();
            NormalState normalState = (slider.getStartPoint().getNormalState() == null) ? new NormalState() : slider.getStartPoint().getNormalState();
            PressedState pressedState = (slider.getStartPoint().getPressedState() == null) ? new PressedState() : slider.getStartPoint().getPressedState();
            if (reachedState.getTrigger() != null) {
                if (reachedState.getTrigger().getCommandMap() != null && !reachedState.getTrigger().getCommandMap().isEmpty()) {
                    reachedState.getTrigger().getCommandMap().keySet().forEach(commandKey -> {
                        BaseCommand baseCommand = reachedState.getTrigger().getCommandMap().get(commandKey);
                        if (baseCommand instanceof VariableCommand) {
                            editVarConst((VariableCommand) baseCommand);
                        }
                    });
                }
            }
            if (reachedDownState.getTrigger() != null) {
                if (reachedDownState.getTrigger().getCommandMap() != null && !reachedDownState.getTrigger().getCommandMap().isEmpty()) {
                    reachedDownState.getTrigger().getCommandMap().keySet().forEach(commandKey -> {
                        BaseCommand baseCommand = reachedDownState.getTrigger().getCommandMap().get(commandKey);
                        if (baseCommand instanceof VariableCommand) {
                            editVarConst((VariableCommand) baseCommand);
                        }
                    });
                }
            }
            if (normalState.getTrigger() != null) {
                if (normalState.getTrigger().getCommandMap() != null && !normalState.getTrigger().getCommandMap().isEmpty()) {
                    normalState.getTrigger().getCommandMap().keySet().forEach(commandKey -> {
                        BaseCommand baseCommand = normalState.getTrigger().getCommandMap().get(commandKey);
                        if (baseCommand instanceof VariableCommand) {
                            editVarConst((VariableCommand) baseCommand);
                        }
                    });
                }
            }
            if (pressedState.getTrigger() != null) {
                if (pressedState.getTrigger().getCommandMap() != null && !pressedState.getTrigger().getCommandMap().isEmpty()) {
                    pressedState.getTrigger().getCommandMap().keySet().forEach(commandKey -> {
                        BaseCommand baseCommand = pressedState.getTrigger().getCommandMap().get(commandKey);
                        if (baseCommand instanceof VariableCommand) {
                            editVarConst((VariableCommand) baseCommand);
                        }
                    });
                }
            }
            judgeAddMap(slider, key, newMap, isGroup);
        } else {
            judgeVariableCommand(baseView, key, newMap, isGroup);
        }
    }

    private Map<String, String> varMap = new HashMap<>();

    private void judgeVariableCommand(BaseView baseView, String key, LinkedHashMap<String, BaseView> newMap, boolean isGroup) {
        if (baseView instanceof Var) {
            Var var = (Var) baseView;
            if (!"notification".equals(isNullJudge(var.getName()))) {
                varMap.put(isNullJudge(var.getName()), isNullJudge(var.getConstString()));
                if (!"-".equals(isNullJudge(var.getConstString()))) {
                    var.setConstString(var.getConstString());
                }
//                if (!"unlock_dist".equals(isNullJudge(var.getName())) || !"move_dx".equals(isNullJudge(var.getName()))
//                        || !"move_dy".equals(isNullJudge(var.getName())) || !"move_radius".equals(isNullJudge(var.getName()))) {
//                    var.setPersist("true");
//                }
                judgeAddMap(var, key, newMap, isGroup);
            }
        } else if (baseView instanceof ExternalCommands) {
            ExternalCommands externalCommands = (ExternalCommands) baseView;
            if (externalCommands.getTrigger() != null && externalCommands.getTrigger().size() > 0) {
                externalCommands.getTrigger().forEach(trigger -> {
                    if (trigger.getCommandMap() != null && !trigger.getCommandMap().isEmpty()) {
                        trigger.getCommandMap().keySet().forEach(commandKey -> {
                            BaseCommand baseCommand = trigger.getCommandMap().get(commandKey);
                            if (baseCommand instanceof VariableCommand) {
                                editVarConst((VariableCommand) baseCommand);
                            }
                        });
                    }
                });
            }
            judgeAddMap(externalCommands, key, newMap, isGroup);
        } else if (baseView instanceof Button) {
            Button button = (Button) baseView;
            if (button.getTriggers() != null) {
                if (button.getTriggers().getTriggerMap() != null && !button.getTriggers().getTriggerMap().isEmpty()) {
                    button.getTriggers().getTriggerMap().keySet().forEach(trigger -> {
                        if (button.getTriggers().getTriggerMap().get(trigger).getCommandMap() != null && !button.getTriggers().getTriggerMap().get(trigger).getCommandMap().isEmpty()) {
                            button.getTriggers().getTriggerMap().get(trigger).getCommandMap().keySet().forEach(variableCommand -> {
                                BaseCommand baseCommand = button.getTriggers().getTriggerMap().get(trigger).getCommandMap().get(variableCommand);
                                if (baseCommand instanceof VariableCommand) {
                                    editVarConst((VariableCommand) baseCommand);
                                }
                            });
                        }
                    });
                }
            }
            judgeAddMap(button, key, newMap, isGroup);
        } else {
            judgeAddMap(baseView, key, newMap, isGroup);
        }
    }

    private void editVarConst(VariableCommand variableCommand) {
//        varMap.keySet().forEach(key -> {
//            if (isNullJudge(variableCommand.getName()).equals(key)) {
//                if (!"-".equals(varMap.get(key))) {
//                    variableCommand.setConstString(varMap.get(key));
//                }
//            }
//        });
        varMap.keySet().stream()
                .filter(key -> isNullJudge(variableCommand.getName()).equals(key))
                .filter(key -> !"-".equals(varMap.get(key)))
                .forEach(key -> variableCommand.setConstString(varMap.get(key)));
    }

    private void judgeAddMap(BaseView baseView, String key, LinkedHashMap<String, BaseView> newMap, boolean isGroup) {
        if (!isGroup) {
            newMap.put(key, baseView);
        }
    }

    private void editIntentCommand(String oppoPath) {
        File oppoXml = FileUtils.getResFileOfThemeModel(Constants.OPPO, "launchpad");
        File vivoXml = FileUtils.getResFileOfThemeModel(Constants.VIVO, "launchpad");
        IntentCommandUtils.ReadXmlInentCommand(Paths.get(oppoPath), vivoXml.toString(), oppoXml.toString());
    }

    private String isNullJudge(String string) {
        return Optional.ofNullable(string).orElse("-");
    }

    private void copyBG(File fromPath, File toPath, int w, int h, String name) {
        try {
            File file = new File(toPath + File.separator + name + ".jpg");
            FileUtils.copyFile(fromPath.getPath(), file.getPath(), true);
            Thumbnails.of(file).sourceRegion(0, 0, w, h).size(w, h).toFile(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
